#include "lua_function_extension.hpp"
#include "lua.h"
#include "scripting/scripting_api.h"
#include "scripting/scripting_module.h"
#include "utils/log.hpp"

#include <exception>

#include "lua.hpp"
#include <LuaBridge/LuaBridge.h>



LuaFunctionExtension::LuaFunctionExtension(std::string title, const std::string &script_path): IFunctionalScript(std::move(title), std::move(script_path), g_current_module)
{
    
}

LuaFunctionExtension::~LuaFunctionExtension()
{
    
}

void LuaFunctionExtension::execute()
{
    try {
        luabridge::LuaRef main = luabridge::getGlobal(l_, "main");
        if (main.isCallable()) {
            main();
        }
    } catch (std::exception &e) {
        L_ERROR("Failed to call lua script!");
    }
}

IScript* LuaFunctionExtension::create(std::string title, std::string_view code, const std::string &script_path)
{
    auto ext = new LuaFunctionExtension(std::move(title), script_path);
    if (!ext->compile(code))
    {
        delete ext;
        ext = nullptr;
    }
    return ext;
}

bool LuaFunctionExtension::compile(const std::string_view& code) const
{
    int r = luaL_loadbuffer(l_, code.data(), code.length(), "script.lua");
    if (r != LUA_OK) {
        const char *errmsg = lua_tolstring(l_, -1, nullptr);
        if (errmsg != nullptr)
            L_ERROR("lua load error: %s", errmsg);
        lua_pop(l_, 1);
    }
    else
    {
        r = lua_pcall(l_, 0, 0, 0);
        if (r != LUA_OK) {
            const char *errmsg = lua_tolstring(l_, -1, nullptr);
            if (errmsg != nullptr)
                L_ERROR("lua execute error: %s", errmsg);
            lua_pop(l_, 1);
        }
    }
    return r == LUA_OK && lua_getglobal(l_, "main") == LUA_TFUNCTION;
}
